﻿#include "module_loader.h"
#include <QDir>
#include <QCoreApplication>
#include <QDebug>
#include <QMessageBox>

ModuleLoader::ModuleLoader(QObject *parent)
    : QObject(parent)
{
}

ModuleLoader::~ModuleLoader()
{
    cleanup();
}

bool ModuleLoader::loadModules()
{
    // 获取应用程序目录
    QString appDir = QCoreApplication::applicationDirPath();
    
    // 定义要加载的库文件
    QMap<QString, QString> libraryFiles;
    
#ifdef Q_OS_WIN
    libraryFiles["HMI"] = appDir + "/hmi_library.dll";
    libraryFiles["PLC"] = appDir + "/plc_library.dll";
#else
    libraryFiles["HMI"] = appDir + "/libhmi_library.so";
    libraryFiles["PLC"] = appDir + "/libplc_library.so";
#endif
    
    int loadedCount = 0;
    int totalCount = libraryFiles.size();
    
    // 加载每个库文件
    for (auto it = libraryFiles.begin(); it != libraryFiles.end(); ++it)
    {
        const QString& moduleName = it.key();
        const QString& libraryPath = it.value();
        
        if (loadLibrary(libraryPath, moduleName))
        {
            loadedCount++;
            qDebug() << u8"成功加载模块库:" << moduleName;
        }
        else
        {
            qWarning() << u8"无法加载模块库:" << moduleName << u8"路径:" << libraryPath;
        }
    }
    
    // 显示加载结果
    if (loadedCount == 0)
    {
        QMessageBox::critical(nullptr, u8"错误", u8"所有模块库加载失败，应用程序无法正常运行。");
        return false;
    }
    else if (loadedCount < totalCount)
    {
        QString message = QString(u8"部分模块库加载失败（%1/%2），某些功能可能不可用。\n\n已加载的模块：").arg(loadedCount).arg(totalCount);
        QStringList availableModules = getAvailableModules();
        for (const QString& module : availableModules)
        {
            message += "\n- " + module;
        }
        QMessageBox::warning(nullptr, u8"警告", message);
    }
    else
    {
        qDebug() << u8"所有模块库加载成功";
    }
    
    return loadedCount > 0;  // 只要有一个库加载成功就返回true
}

bool ModuleLoader::loadLibrary(const QString& libraryPath, const QString& moduleName)
{
    // 检查库文件是否存在
    if (!QFile::exists(libraryPath))
    {
        qWarning() << u8"库文件不存在:" << libraryPath;
        return false;
    }
    
    // 创建库对象
    QLibrary* library = new QLibrary(libraryPath);
    
    // 加载库
    if (!library->load())
    {
        qWarning() << u8"加载库失败:" << library->errorString();
        delete library;
        return false;
    }
    
    // 获取创建函数
    CreateModuleFunc createFunc = (CreateModuleFunc)library->resolve(CREATE_MODULE_FUNC_NAME);
    if (!createFunc)
    {
        qWarning() << u8"无法解析创建函数:" << CREATE_MODULE_FUNC_NAME;
        library->unload();
        delete library;
        return false;
    }
    
    // 获取工厂函数（可选）
    CreateFactoryFunc factoryFunc = (CreateFactoryFunc)library->resolve(CREATE_FACTORY_FUNC_NAME);
    
    // 存储库和函数
    libraries_[moduleName] = library;
    createFuncs_[moduleName] = createFunc;
    if (factoryFunc)
    {
        factoryFuncs_[moduleName] = factoryFunc;
    }
    
    qDebug() << u8"成功加载模块:" << moduleName;
    return true;
}

IModule* ModuleLoader::createModule(const QString& moduleName, QWidget* ui, ModbusManager* modbusManager, QObject* parent)
{
    if (!isModuleAvailable(moduleName))
    {
        qWarning() << u8"模块不可用:" << moduleName;
        return nullptr;
    }
    
    CreateModuleFunc createFunc = createFuncs_[moduleName];
    if (!createFunc)
    {
        qWarning() << u8"创建函数不可用:" << moduleName;
        return nullptr;
    }
    
    // 创建模块实例
    IModule* module = createFunc(ui, modbusManager, parent);
    if (!module)
    {
        qWarning() << u8"创建模块实例失败:" << moduleName;
        return nullptr;
    }
    
    qDebug() << u8"成功创建模块:" << moduleName;
    return module;
}

QStringList ModuleLoader::getAvailableModules() const
{
    return createFuncs_.keys();
}

bool ModuleLoader::isModuleAvailable(const QString& moduleName) const
{
    return createFuncs_.contains(moduleName);
}

void ModuleLoader::cleanup()
{
    // 卸载所有库
    for (auto it = libraries_.begin(); it != libraries_.end(); ++it)
    {
        QLibrary* library = it.value();
        if (library)
        {
            library->unload();
            delete library;
        }
    }
    
    libraries_.clear();
    createFuncs_.clear();
    factoryFuncs_.clear();
}
